#include <iostream>
#include <fstream>
#include <vector>
#include <opencv2/opencv.hpp>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
}

// 从指定文件读取二进制数据
bool read_binary_file(const std::string& filename, std::vector<unsigned char>& binary_data) {
    std::ifstream infile(filename, std::ios::binary);
    if (!infile) {
        std::cerr << "Error: Could not open file " << filename << std::endl;
        return false;
    }

    // 读取文件内容到 binary_data
    binary_data.assign(std::istreambuf_iterator<char>(infile), std::istreambuf_iterator<char>());
    infile.close();

    std::cout << "Read binary file: " << filename << " (" << binary_data.size() << " bytes)" << std::endl;
    return true;
}

// 编码二进制文件为视频 in.mp4，时长约 3秒（3000ms）
void encode(const std::string& input_bin, const std::string& output_mp4, int duration_ms) {
    // 从文件读取二进制数据
    std::vector<unsigned char> binary_data;
    if (!read_binary_file(input_bin, binary_data)) {
        return;
    }

    av_register_all();
    avcodec_register_all();
    AVFormatContext* formatContext = nullptr;
    AVCodecContext* codecContext = nullptr;
    AVStream* stream = nullptr;

    // 创建视频文件输出
    if (avformat_alloc_output_context2(&formatContext, nullptr, nullptr, output_mp4.c_str()) < 0) {
        std::cerr << "Could not create output context" << std::endl;
        return;
    }

    AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);
    if (!codec) {
        std::cerr << "Codec not found!" << std::endl;
        return;
    }

    stream = avformat_new_stream(formatContext, codec);
    codecContext = avcodec_alloc_context3(codec);

    codecContext->width = 640;  // Example width
    codecContext->height = 480; // Example height
    codecContext->bit_rate = 400000;
    codecContext->time_base = { 1, 30 };  // 30 fps
    codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
    codecContext->gop_size = 12;  // Group of pictures size
    codecContext->max_b_frames = 2;

    if (avcodec_open2(codecContext, codec, nullptr) < 0) {
        std::cerr << "Failed to open codec!" << std::endl;
        return;
    }

    if (avio_open(&formatContext->pb, output_mp4.c_str(), AVIO_FLAG_WRITE) < 0) {
        std::cerr << "Could not open output file!" << std::endl;
        return;
    }

    if (avformat_write_header(formatContext, nullptr) < 0) {
        std::cerr << "Error occurred when writing header!" << std::endl;
        return;
    }

    // 生成视频帧
    int frame_count = binary_data.size() / (640 * 480 * 3);  // Example for RGB frames
    for (int i = 0; i < frame_count; ++i) {
        AVFrame* frame = av_frame_alloc();
        frame->format = codecContext->pix_fmt;
        frame->width = codecContext->width;
        frame->height = codecContext->height;

        if (av_frame_get_buffer(frame, 32) < 0) {
            std::cerr << "Could not allocate frame buffer!" << std::endl;
            return;
        }

        // 填充二进制数据到帧
        for (int y = 0; y < frame->height; ++y) {
            for (int x = 0; x < frame->width; ++x) {
                frame->data[0][y * frame->linesize[0] + x] = binary_data[i * (640 * 480 * 3) + y * frame->width + x];
            }
        }

        AVPacket pkt;
        av_init_packet(&pkt);
        pkt.data = nullptr;
        pkt.size = 0;

        if (avcodec_receive_packet(codecContext, &pkt) == 0) {
            av_write_frame(formatContext, &pkt);
        }

        av_frame_free(&frame);
    }

    av_write_trailer(formatContext);
    avcodec_free_context(&codecContext);
    avformat_free_context(formatContext);
}

// 模拟翻拍视频
void simulate_flip(const std::string& input_video, const std::string& output_video) {
    cv::VideoCapture cap(input_video);
    if (!cap.isOpened()) {
        std::cerr << "Error: Could not open input video file!" << std::endl;
        return;
    }

    cv::VideoWriter out(output_video, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 30, cv::Size(640, 480));

    while (true) {
        cv::Mat frame;
        cap >> frame;
        if (frame.empty()) {
            break;
        }

        // 模拟翻拍效果（如高斯模糊）
        cv::GaussianBlur(frame, frame, cv::Size(5, 5), 0);
        out.write(frame);
    }

    cap.release();
    out.release();
}

// 解码视频
void decode(const std::string& input_mp4, const std::string& output_bin, const std::string& output_validity) {
    av_register_all();
    avcodec_register_all();
    AVFormatContext* formatContext = nullptr;
    AVCodecContext* codecContext = nullptr;

    if (avformat_open_input(&formatContext, input_mp4.c_str(), nullptr, nullptr) != 0) {
        std::cerr << "Could not open source file!" << std::endl;
        return;
    }

    if (avformat_find_stream_info(formatContext, nullptr) < 0) {
        std::cerr << "Could not find stream information!" << std::endl;
        return;
    }

    int video_stream_index = -1;
    for (unsigned int i = 0; i < formatContext->nb_streams; i++) {
        if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_index = i;
            break;
        }
    }

    if (video_stream_index == -1) {
        std::cerr << "Could not find video stream!" << std::endl;
        return;
    }

    AVCodec* codec = avcodec_find_decoder(formatContext->streams[video_stream_index]->codecpar->codec_id);
    if (!codec) {
        std::cerr << "Codec not found!" << std::endl;
        return;
    }

    codecContext = avcodec_alloc_context3(codec);
    if (avcodec_parameters_to_context(codecContext, formatContext->streams[video_stream_index]->codecpar) < 0) {
        std::cerr << "Could not copy codec parameters!" << std::endl;
        return;
    }

    if (avcodec_open2(codecContext, codec, nullptr) < 0) {
        std::cerr << "Could not open codec!" << std::endl;
        return;
    }

    AVPacket packet;
    AVFrame* frame = av_frame_alloc();
    std::ofstream outfile(output_bin, std::ios::binary);
    std::ofstream validityfile(output_validity, std::ios::binary);

    while (av_read_frame(formatContext, &packet) >= 0) {
        if (packet.stream_index == video_stream_index) {
            int ret = avcodec_send_packet(codecContext, &packet);
            if (ret < 0) {
                std::cerr << "Error sending packet to decoder!" << std::endl;
                continue;
            }

            ret = avcodec_receive_frame(codecContext, frame);
            if (ret < 0) {
                std::cerr << "Error receiving frame!" << std::endl;
                continue;
            }

            // 提取并写入二进制数据和有效性标志
            for (int y = 0; y < frame->height; ++y) {
                for (int x = 0; x < frame->width; ++x) {
                    unsigned char value = frame->data[0][y * frame->linesize[0] + x];
                    outfile.write(reinterpret_cast<char*>(&value), sizeof(value));
                    validityfile.put(0xFF);  // 假设全部有效
                }
            }
        }
        av_packet_unref(&packet);
    }

    outfile.close();
    validityfile.close();main
    av_frame_free(&frame);
    avcodec_free_context(&codecContext);
    avformat_close_input(&formatContext);
}

// 验证二进制文件和有效性
bool verify_binary(const std::string& original, const std::string& decoded, const std::string& validity) {
    std::ifstream orig_file
